package org.web.clientlistmanager.server.biz;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.web.base.domain.ResultDO;
import org.web.base.domain.helper.ResultHelper;
import org.web.base.domain.helper.ServiceExceptionHelper;
import org.web.base.domain.helper.ValidationHelper;
import org.web.clientlistmanager.sdk.biz.ClmClientProcessBiz;
import org.web.clientlistmanager.sdk.dto.*;
import org.web.clientlistmanager.server.domain.ClientProcessDO;
import org.web.clientlistmanager.server.domain.ClientTypeListDO;
import org.web.clientlistmanager.server.domain.query.QueryClientProcess;
import org.web.clientlistmanager.server.dto.query.QueryClientProcessRequest;
import org.web.clientlistmanager.server.service.ClientProcessService;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service("clmClientProcessBiz")
public class ClmClientProcessBizImpl implements ClmClientProcessBiz {

    private static final Logger logger = Logger.getLogger(ClmClientProcessBizImpl.class);

    @Resource
    private ClientProcessService clientProcessService;

    @Resource
    private ClmBatchBizImpl batchClmBiz;


    public ResultDO<String> saveLocalClientProcessDTO(LocalClientProcessDTO localClientProcessDTO) {
        ResultDO<String> resultDO = new ResultDO<>();
        try {
            ClmHelper.validateLocalClientProcessDTO(localClientProcessDTO);
            List<ClientTypeListDO> clientTypeListDOList = null;
            if (localClientProcessDTO.getLocalClientTypeDetailDTOList() != null && localClientProcessDTO.getLocalClientTypeDetailDTOList().size() > 0) {
                clientTypeListDOList = new ArrayList<>();
                for (LocalClientTypeListDTO localClientTypeListDTO : localClientProcessDTO.getLocalClientTypeDetailDTOList()) {
                    ClientTypeListDO clientTypeListDO = new ClientTypeListDO();
                    BeanUtils.copyProperties(clientTypeListDO, localClientTypeListDTO);
                    clientTypeListDOList.add(clientTypeListDO);
                }
            }

            ClientProcessDO clientProcessDO = new ClientProcessDO();
            BeanUtils.copyProperties(clientProcessDO, localClientProcessDTO);
            clientProcessDO.setProcessLastBeatTime(new Date());
            QueryClientProcess queryClientProcess = new QueryClientProcess();
            if (ClientListManagerConstant.IS_UNIQUE_PER_IP.Y.name().equals(localClientProcessDTO.getIsUniquePerIp())) {
                // 在同一个结点中，某个微服务应用只部署一个，即针对某个微服务，不允许同一个结点部署两个以及两个以上。
                // 该场合下，（1）需要清除掉之前结点信息,即清楚之前所有processUuid相同的ClientProcess信息。（2）新增结点进程信息
                queryClientProcess.setClientServiceName(localClientProcessDTO.getClientServiceName());
                queryClientProcess.setClientAddress(localClientProcessDTO.getClientAddress());
                queryClientProcess.setAllRecords();
                List<ClientProcessDO> list = clientProcessService.selectClientProcessList(queryClientProcess);

                boolean isClientProcessExist = false;
                List<String> deleteProcessUuidList = new ArrayList<>();
                for (ClientProcessDO clientProcessDOFromDB : list) {
                    if (!clientProcessDOFromDB.getProcessUuid().equals(localClientProcessDTO.getProcessUuid())) {
                        deleteProcessUuidList.add(clientProcessDOFromDB.getProcessUuid());
                    } else {
                        isClientProcessExist = true; // 该结点进程信息已存在，则不做任何处理。说明之前已经创注册过了。
                        resultDO.setDomain(String.valueOf(clientProcessDOFromDB.getClientProcessId()));
                    }
                }
                batchClmBiz.deleteRegisteredInfoByProcessUuidList(deleteProcessUuidList);
                if (!isClientProcessExist) {
                    // 该结点进程信息已存在，则不做任何处理。说明之前已经创注册过了。
                    batchClmBiz.saveClientProcessAndClientTypeDetailDTOList(clientProcessDO, clientTypeListDOList);
                }
            } else {
                queryClientProcess.setProcessUuid(localClientProcessDTO.getProcessUuid());
                ClientProcessDO ClientProcessDOFromDB = clientProcessService.selectOneClientProcess(queryClientProcess);
                if (ClientProcessDOFromDB == null) {
                    batchClmBiz.saveClientProcessAndClientTypeDetailDTOList(clientProcessDO, clientTypeListDOList);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(ServiceExceptionHelper.getExceptionInfo(e));
            resultDO = ResultHelper.buildResultDOByException(e, localClientProcessDTO.getProcessUuid());
        }
        return resultDO;
    }


    @Override
    public ResultDO<List<LocalClientProcessDTO>> selectClientProcessList(QueryClientProcessRequest queryClientProcessReq) {
        ResultDO<List<LocalClientProcessDTO>> resultDO = new ResultDO<>();
        try {
            ValidationHelper.validateAndThrow(QueryClientProcessRequest.class, queryClientProcessReq);
            QueryClientProcess queryClientProcess = new QueryClientProcess();
            BeanUtils.copyProperties(queryClientProcess, queryClientProcessReq);
            ResultDO<List<ClientProcessDO>> selectResult = clientProcessService.selectClientProcessListResult(queryClientProcess);
            if (selectResult.isSuccess()) {
                List<LocalClientProcessDTO> list = new ArrayList<>();
                resultDO.setDomain(list);
                for (ClientProcessDO clientProcessDO : selectResult.getDomain()) {
                    LocalClientProcessDTO localClientProcessDTO = new LocalClientProcessDTO();
                    BeanUtils.copyProperties(localClientProcessDTO, clientProcessDO);
                    list.add(localClientProcessDTO);
                }
                resultDO.setTotalCount(selectResult.getTotalCount());
            } else {
                BeanUtils.copyProperties(resultDO, selectResult);
            }
        } catch (Exception e) {
            logger.error(ServiceExceptionHelper.getExceptionInfo(e));
            resultDO = ResultHelper.buildResultDOByException(e);
        }
        return resultDO;
    }
}
